// ============================================
// internal/service/event_service.go
// ============================================

package service

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
	"libvirt.org/go/libvirt"

	"virt-manager-go/internal/domain"
)

type eventService struct {
	connMgr domain.ConnectionManager
	logger  *logrus.Logger

	// 订阅管理
	subscriptions   map[string]*subscription
	subscriptionsMu sync.RWMutex

	// 事件历史
	eventHistory   []*domain.Event
	eventHistoryMu sync.RWMutex
	maxHistorySize int

	// 事件监听器
	listeners   map[string]*eventListener
	listenersMu sync.RWMutex
}

type subscription struct {
	id      string
	filter  *domain.EventFilter
	eventCh chan *domain.Event
	ctx     context.Context
	cancel  context.CancelFunc
}

type eventListener struct {
	connID       string
	conn         *libvirt.Connect
	callbackID   int
	stopCh       chan struct{}
	eventService *eventService
}

func NewEventService(connMgr domain.ConnectionManager, logger *logrus.Logger) domain.EventService {
	return &eventService{
		connMgr:        connMgr,
		logger:         logger,
		subscriptions:  make(map[string]*subscription),
		eventHistory:   make([]*domain.Event, 0, 1000),
		maxHistorySize: 1000,
		listeners:      make(map[string]*eventListener),
	}
}

// Subscribe 订阅事件
func (s *eventService) Subscribe(ctx context.Context, filter *domain.EventFilter) (<-chan *domain.Event, error) {
	subID := uuid.New().String()

	subCtx, cancel := context.WithCancel(ctx)
	sub := &subscription{
		id:      subID,
		filter:  filter,
		eventCh: make(chan *domain.Event, 100), // 缓冲 100 个事件
		ctx:     subCtx,
		cancel:  cancel,
	}

	s.subscriptionsMu.Lock()
	s.subscriptions[subID] = sub
	s.subscriptionsMu.Unlock()

	s.logger.WithField("subscription_id", subID).Info("Event subscription created")

	// 自动清理订阅
	go func() {
		<-subCtx.Done()
		s.Unsubscribe(subID)
	}()

	return sub.eventCh, nil
}

// Unsubscribe 取消订阅
func (s *eventService) Unsubscribe(subscriptionID string) {
	s.subscriptionsMu.Lock()
	defer s.subscriptionsMu.Unlock()

	if sub, exists := s.subscriptions[subscriptionID]; exists {
		sub.cancel()
		close(sub.eventCh)
		delete(s.subscriptions, subscriptionID)
		s.logger.WithField("subscription_id", subscriptionID).Info("Event subscription removed")
	}
}

// GetEvents 获取历史事件
func (s *eventService) GetEvents(ctx context.Context, filter *domain.EventFilter, limit int) ([]*domain.Event, error) {
	s.eventHistoryMu.RLock()
	defer s.eventHistoryMu.RUnlock()

	if limit <= 0 || limit > len(s.eventHistory) {
		limit = len(s.eventHistory)
	}

	// 应用过滤器
	events := make([]*domain.Event, 0, limit)
	for i := len(s.eventHistory) - 1; i >= 0 && len(events) < limit; i-- {
		event := s.eventHistory[i]
		if s.matchesFilter(event, filter) {
			events = append(events, event)
		}
	}

	return events, nil
}

// StartListening 启动事件监听
func (s *eventService) StartListening(ctx context.Context, connID string) error {
	s.listenersMu.Lock()
	defer s.listenersMu.Unlock()

	// 检查是否已经在监听
	if _, exists := s.listeners[connID]; exists {
		return fmt.Errorf("already listening on connection: %s", connID)
	}

	conn, err := s.connMgr.GetConnection(connID)
	if err != nil {
		return err
	}

	// 注册 libvirt 事件回调
	callbackID, err := conn.DomainEventLifecycleRegister(nil, func(c *libvirt.Connect, d *libvirt.Domain, event *libvirt.DomainEventLifecycle) {
		s.handleDomainLifecycleEvent(connID, d, event)
	})

	if err != nil {
		return fmt.Errorf("failed to register event callback: %w", err)
	}

	listener := &eventListener{
		connID:       connID,
		conn:         conn,
		callbackID:   callbackID,
		stopCh:       make(chan struct{}),
		eventService: s,
	}

	s.listeners[connID] = listener

	// 启动事件循环
	go s.runEventLoop(ctx, listener)

	s.logger.WithField("connection", connID).Info("Started event listening")

	return nil
}

// StopListening 停止事件监听
func (s *eventService) StopListening(ctx context.Context, connID string) error {
	s.listenersMu.Lock()
	defer s.listenersMu.Unlock()

	if listener, exists := s.listeners[connID]; exists {
		close(listener.stopCh)
		listener.conn.DomainEventDeregister(listener.callbackID)
		delete(s.listeners, connID)
		s.logger.WithField("connection", connID).Info("Stopped event listening")
	}

	return nil
}

// runEventLoop 运行事件循环
func (s *eventService) runEventLoop(ctx context.Context, listener *eventListener) {
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-listener.stopCh:
			return
		case <-ticker.C:
			// libvirt 事件循环需要定期调用
			if err := libvirt.EventRunDefaultImpl(); err != nil {
				s.logger.WithError(err).Error("Event loop error")
			}
		}
	}
}

// handleDomainLifecycleEvent 处理虚拟机生命周期事件
func (s *eventService) handleDomainLifecycleEvent(connID string, dom *libvirt.Domain, libvirtEvent *libvirt.DomainEventLifecycle) {
	domName, _ := dom.GetName()

	action := s.mapLifecycleEvent(libvirtEvent.Event)
	detail := s.mapLifecycleDetail(libvirtEvent.Detail)

	event := &domain.Event{
		ID:        uuid.New().String(),
		Type:      domain.EventTypeVM,
		Category:  domain.EventCategoryLifecycle,
		Source:    connID,
		Target:    domName,
		Action:    action,
		Detail:    detail,
		Timestamp: time.Now(),
		Metadata: map[string]any{
			"event_type":   libvirtEvent.Event,
			"event_detail": libvirtEvent.Detail,
		},
	}

	s.publishEvent(event)
}

// publishEvent 发布事件
func (s *eventService) publishEvent(event *domain.Event) {
	// 添加到历史
	s.addToHistory(event)

	// 发送给所有订阅者
	s.subscriptionsMu.RLock()
	defer s.subscriptionsMu.RUnlock()

	for _, sub := range s.subscriptions {
		if s.matchesFilter(event, sub.filter) {
			select {
			case sub.eventCh <- event:
			case <-sub.ctx.Done():
			default:
				// 通道已满，丢弃事件
				s.logger.Warn("Event channel full, dropping event")
			}
		}
	}

	s.logger.WithFields(logrus.Fields{
		"type":   event.Type,
		"target": event.Target,
		"action": event.Action,
	}).Debug("Event published")
}

// addToHistory 添加到历史记录
func (s *eventService) addToHistory(event *domain.Event) {
	s.eventHistoryMu.Lock()
	defer s.eventHistoryMu.Unlock()

	s.eventHistory = append(s.eventHistory, event)

	// 限制历史记录大小
	if len(s.eventHistory) > s.maxHistorySize {
		s.eventHistory = s.eventHistory[len(s.eventHistory)-s.maxHistorySize:]
	}
}

// matchesFilter 检查事件是否匹配过滤器
func (s *eventService) matchesFilter(event *domain.Event, filter *domain.EventFilter) bool {
	if filter == nil {
		return true
	}

	// 检查类型
	if len(filter.Types) > 0 {
		matched := false
		for _, t := range filter.Types {
			if event.Type == t {
				matched = true
				break
			}
		}
		if !matched {
			return false
		}
	}

	// 检查分类
	if len(filter.Categories) > 0 {
		matched := false
		for _, c := range filter.Categories {
			if event.Category == c {
				matched = true
				break
			}
		}
		if !matched {
			return false
		}
	}

	// 检查来源
	if len(filter.Sources) > 0 {
		matched := false
		for _, s := range filter.Sources {
			if event.Source == s {
				matched = true
				break
			}
		}
		if !matched {
			return false
		}
	}

	// 检查目标
	if len(filter.Targets) > 0 {
		matched := false
		for _, t := range filter.Targets {
			if event.Target == t {
				matched = true
				break
			}
		}
		if !matched {
			return false
		}
	}

	// 检查动作
	if len(filter.Actions) > 0 {
		matched := false
		for _, a := range filter.Actions {
			if event.Action == a {
				matched = true
				break
			}
		}
		if !matched {
			return false
		}
	}

	// 检查时间范围
	if filter.StartTime != nil && event.Timestamp.Before(*filter.StartTime) {
		return false
	}
	if filter.EndTime != nil && event.Timestamp.After(*filter.EndTime) {
		return false
	}

	return true
}

// mapLifecycleEvent 映射生命周期事件
func (s *eventService) mapLifecycleEvent(event libvirt.DomainEventType) string {
	switch event {
	case libvirt.DOMAIN_EVENT_DEFINED:
		return "defined"
	case libvirt.DOMAIN_EVENT_UNDEFINED:
		return "undefined"
	case libvirt.DOMAIN_EVENT_STARTED:
		return "started"
	case libvirt.DOMAIN_EVENT_SUSPENDED:
		return "suspended"
	case libvirt.DOMAIN_EVENT_RESUMED:
		return "resumed"
	case libvirt.DOMAIN_EVENT_STOPPED:
		return "stopped"
	case libvirt.DOMAIN_EVENT_SHUTDOWN:
		return "shutdown"
	case libvirt.DOMAIN_EVENT_PMSUSPENDED:
		return "pmsuspended"
	case libvirt.DOMAIN_EVENT_CRASHED:
		return "crashed"
	default:
		return "unknown"
	}
}

// mapLifecycleDetail 映射生命周期详情
func (s *eventService) mapLifecycleDetail(detail int) string {
	// 这里可以根据不同的事件类型映射详细信息
	return fmt.Sprintf("detail-%d", detail)
}
